<?php
    require_once 'common.php';

    class Dir
    {
        private $FDir;

        /**
         * Removes directory name
         * 
         * @param string $name the directory to be removed
         * @param bool $removeSubs wether or not to remove subdirectories
         * @return bool true/false depending on operation success
         */
        private function delDir($name, $removeSubs)
        {
            if (!is_dir($name))
                return false;
            
            if ($removeSubs)
            {
                $f = scandir($name); 
                
                foreach ($f as $file)
                {
                    // Skipping . and ..
                    if (($file != ".") && ($file != ".."))
                    {
                        // Getting the full filename
                        $fn = "{$name}/{$file}";
                        
                        if (is_file($fn))
                            unlink($fn);
                          
                        // If it's a directory
                        // also remove this recursively
                        if (is_dir($fn))
                            $this->delDir($fn, $removeSubs);  
                    }
                } 
                
                // At this point the original directory
                // is also removed
                return rmdir($name); 
            }
            else
                return rmdir($name);    
        }
        
        private function dirEnumFilesRec($dir, $recursive = false, &$files, &$dirs)
        {
            # In case of inability to open the specified
            # Directory, suppress warnings
            # and return
            if (!($h = @opendir($dir)))
                return;
               
            $dir = includeTrailingBackslash($dir);  
            $file = "";
            
            while (false !== ($file = readdir($h))) 
            {
            	$full_path = $dir . $file;
            	
                if (($file != "..") && ($file != "."))
                {              
                    if (is_file($full_path))
                        $files[] = $full_path;
                    else
                    {
                        $dirs[] = $full_path;
                        
                        if ($recursive)
                            $this->dirEnumFilesRec($full_path, true, $files, $dirs);  
                    }  
                }
            }
            
            closedir($h);
        }   
        
        private function dirEnumFiles($dir, $recursive)
        {
            $files = array();
            $dirs = array();
        
            $this->dirEnumFilesRec($dir, $recursive, $files, $dirs);
            
            sort($dirs);
            sort($files);

            return array_merge($dirs, $files);
        }   
        
        /**
         * Creates the path passed in the argument
         * 
         * @param string $Path the path to create
         */
        function createPath($Path)
        {
            $f = explode('/', $Path);
            
            for ($i=0; $i<count($f); $i++)
            {          
                // p is the directory to create
                $p = "";
                
                // Saving in p the directory to create
                // mkdir is unable to create paths
                // so they will have to be created manually
                // on each level
                //
                // ex:
                //   i = 0; p = hi
                //   i = 1; p = hi/test;
                //   i = 2; p = hi/test/bin
                // etc
                //
                for ($j=0; $j<=$i; $j++)
                    $p .= $f[$j] . '/';

                if (!file_exists($p))
                    if (!mkdir($p))
                        throw new Exception("Unable to create directory '$p'");
            }
        }
        
        /**
         * Returns the directory name
         * 
         */
        function getName()
        {
            return basename(realpath($this->FDir));
        }
        
        /**
         * Returns the path to this directory
         */
        function getPath()
        {
            if ($this->FDir == './')
                return '../';
            
            $f = explode('/', exludeTrailingBackslash($this->FDir));
                  
            array_pop($f);
            
            return implode('/', $f);     
        }
        
        /**
         * Returns parent directory's name
         */
        function getParentDir()
        {
            $f = explode('/', $this->FDir);
            
            return $f [ count($f) - 1];     
        }
        
        /**
         * Chechs wether this directory exists
         */ 
        function exists()
        {
            return file_exists($this->FDir);
        }
        
        /**
         * Renames the directory
         */
        function ren($newName)
        {
            if (file_exists($newName))
                return false;
                
            $b = @rename($this->FDir, $newName);
            
            if ($b)
                $this->setFullPath(($this->path() != "") ? $this->path() . '/' . $newName : $newName);
            
            return $b;
        }
        
        /**
         * Checks wether this directory is empty
         * 
         */
        function isEmpty()
        {    
            return (count($this->enumFiles()) > 0);
        }
              
        /**
         * Deletes this directory
         */
        function delete($removeSubs = false)
        {
            return $this->delDir($this->FDir, $removeSubs);
        }
        
        
        /**
         * Returns the file list this directory contains
         * 
         * @param bool $includeSubdirs indicates wether to add 
         * subdirectories and their files to the list
         */
        function enumFiles($includeSubdirs = false)
        {
            return @$this->dirEnumFiles($this->FDir, $includeSubdirs);
        }
        
        function getFullPath()
        {
            return $this->FDir;
        }
        
        function setFullPath($dir)
        {
            $this->FDir = includeTrailingBackslash($dir);
        }
        
        /**
         * Constructor
         * 
         * @param string name the working directory
         */
        function __construct($name)
        {
            $this->setFullPath(str_replace('\\', '/', realpath($name)));
        }
    }
?>
